package com.pactera.elasticsearch.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.SystemPropertyUtils;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

/**
 * 包扫描工具
 *
 * @author: liqingdian
 */
public class SpringScanUtils implements ResourceLoaderAware {

    private static final Logger LOG = LoggerFactory.getLogger(SpringScanUtils.class);
    /**
     * Spring容器注入
     */
    private static ResourceLoader resourceLoader;
    private static ResourcePatternResolver resolver;
    private static MetadataReaderFactory metadataReaderFactory;

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        if (this.resourceLoader == null) {
            this.resourceLoader = resourceLoader;
            this.resolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
            this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
        }
    }

    public static ResourceLoader getResourceLoader() {
        return resourceLoader;
    }

    public static ResourcePatternResolver getResolver() {
        return resolver;
    }

    public static MetadataReaderFactory getFactory() {
        return metadataReaderFactory;
    }

    public static Set<Class<?>> doScan(String scanPath) throws IOException {
        Set<Class<?>> classes = new HashSet<Class<?>>();
        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                .concat(ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(scanPath))
                        .concat("/**/*.class"));
        Resource[] resources = getResolver().getResources(packageSearchPath);
        MetadataReader metadataReader;
        for (Resource resource : resources) {
            if (resource.isReadable()) {
                metadataReader = getFactory().getMetadataReader(resource);
                try {
                    if (metadataReader.getClassMetadata().isConcrete()) {// 当类型不是抽象类或接口,添加到集合
                        classes.add(Class.forName(metadataReader.getClassMetadata().getClassName()));
                    }
                } catch (Exception e) {
                    LOG.error(e.getMessage(), e);
                }
            }
        }
        return classes;
    }
}
